home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / boot / czesc_2 / toolmanager / source / prefs / mainwindow.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  37KB  |  1,146 lines

  1. /*
  2.  * mainwindow.c  V2.1
  3.  *
  4.  * main window handling
  5.  *
  6.  * (c) 1990-1993 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerConf.h"
  10.  
  11. /* Edit windows function tables */
  12. OpenWindowFuncPtr OpenEditWindowFunctions[TMOBJTYPES]={
  13.                                                        OpenExecEditWindow,
  14.                                                        OpenImageEditWindow,
  15.                                                        OpenSoundEditWindow,
  16.                                                        OpenMenuEditWindow,
  17.                                                        OpenIconEditWindow,
  18.                                                        OpenDockEditWindow,
  19.                                                        OpenAccessEditWindow
  20.                                                         };
  21.  
  22. CopyNodeFuncPtr CopyNodeFunctions[TMOBJTYPES]={
  23.                                                CopyExecNode,
  24.                                                CopyImageNode,
  25.                                                CopySoundNode,
  26.                                                CopyMenuNode,
  27.                                                CopyIconNode,
  28.                                                CopyDockNode,
  29.                                                CopyAccessNode
  30.                                               };
  31.  
  32. /* Window data */
  33. static struct Gadget *gl;             /* Gadget list */
  34. static struct Menu *mn;               /* Menu list */
  35. static struct Window *w;              /* Window */
  36. static void *aw;                      /* AppWindow pointer */
  37. static UWORD ww,wh;                   /* Window size */
  38.                                       /* Current list in ListView gadget */
  39. static struct List *CurrentList=&ObjectLists[TMOBJTYPE_EXEC];
  40. static struct Node *CurrentNode=NULL; /* Current selected node */
  41. static struct Node *OldNode;          /* Current edited node */
  42. static ULONG CurrentListNumber=0;     /* Number of the current list */
  43. static LONG CurrentTop=0;             /* Top node ordinal number */
  44. static LONG CurrentOrd=-1;            /* Current node ordinal number */
  45. static ULONG CurrentSeconds=0;
  46. static ULONG CurrentMicros=0;
  47. static OpenWindowFuncPtr OpenEditWindow=OpenExecEditWindow;
  48. static CopyNodeFuncPtr   CopyNode=CopyExecNode;
  49. static FreeNodeFuncPtr   FreeNode=FreeExecNode;
  50. static struct EasyStruct es={sizeof(struct EasyStruct),0,NULL,NULL,NULL};
  51. static char *deftooltypes[]={"USE",NULL};
  52. static struct Requester DummyReq;
  53. #define WINDOW_IDCMP (IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|BUTTONIDCMP|\
  54.                       LISTVIEWIDCMP|CYCLEIDCMP|IDCMP_MENUPICK|IDCMP_VANILLAKEY)
  55.  
  56. /* Gadget data */
  57. #define GAD_TYPE    0
  58. #define GAD_LIST    1
  59. #define GAD_TOP     2
  60. #define GAD_UP      3
  61. #define GAD_DOWN    4
  62. #define GAD_BOTTOM  5
  63. #define GAD_SORT    6
  64. #define GAD_NEW     7
  65. #define GAD_EDIT    8
  66. #define GAD_COPY    9
  67. #define GAD_REMOVE 10
  68. #define GAD_SAVE   11
  69. #define GAD_USE    12
  70. #define GAD_TEST   13
  71. #define GAD_CANCEL 14
  72. #define GADGETS    15
  73. static struct GadgetData gdata[GADGETS];
  74.  
  75. /* Gadget tags */
  76. static char *cyclelabels[TMOBJTYPES+1];
  77. static struct TagItem cycletags[]={GTCY_Labels, (ULONG) cyclelabels,
  78.                                    GTCY_Active, TMOBJTYPE_EXEC,
  79.                                    TAG_DONE};
  80.  
  81. static struct TagItem lvtags[]={GTLV_Labels,
  82.                                  (ULONG) &ObjectLists[TMOBJTYPE_EXEC],
  83.                                 GTLV_ShowSelected, NULL,
  84.                                 TAG_DONE};
  85.  
  86. /* Menu data */
  87. #define MENU_PROJECT  0
  88. #define MENU_OPEN     1
  89. #define MENU_APPEND   2
  90. #define MENU_SAVEAS   3
  91. #define MENU_ABOUT    5
  92. #define MENU_QUIT     7
  93. #define MENU_EDIT     8
  94. #define MENU_LSAVED   9
  95. #define MENU_RESTORE 10
  96. #define MENU_SETTING 11
  97. #define MENU_CRICONS 12
  98. static struct NewMenu mdata[]={
  99.                                {NM_TITLE,NULL,NULL,0,~0,NULL},
  100.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_OPEN},
  101.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_APPEND},
  102.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_SAVEAS},
  103.                                 {NM_ITEM,NM_BARLABEL,NULL,0,~0,NULL},
  104.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_ABOUT},
  105.                                 {NM_ITEM,NM_BARLABEL,NULL,0,~0,NULL},
  106.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_QUIT},
  107.                                {NM_TITLE,NULL,NULL,0,~0,NULL},
  108.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_LSAVED},
  109.                                 {NM_ITEM,NULL,NULL,0,~0,(APTR) MENU_RESTORE},
  110.                                {NM_TITLE,NULL,NULL,0,~0,NULL},
  111.                                 {NM_ITEM,NULL,NULL,0,~1,(APTR) MENU_CRICONS},
  112.                                {NM_END}
  113.                               };
  114.  
  115. /* Gadget vanilla key data */
  116. #define KEY_TYPE   0
  117. #define KEY_SORT   1
  118. #define KEY_NEW    2
  119. #define KEY_EDIT   3
  120. #define KEY_COPY   4
  121. #define KEY_SAVE   5
  122. #define KEY_USE    6
  123. #define KEY_TEST   7
  124. #define KEY_CANCEL 8
  125. static char KeyArray[KEY_CANCEL+1];
  126.  
  127. /* Init main window */
  128. void InitMainWindow(UWORD left, UWORD fheight)
  129. {
  130.  ULONG i,tmp,maxw1,maxw2,maxw3;
  131.  struct GadgetData *gd;
  132.  
  133.  /* Init strings */
  134.  gdata[GAD_TYPE].name  =AppStrings[MSG_MAINWIN_TYPE_GAD];
  135.  gdata[GAD_LIST].name  =AppStrings[MSG_MAINWIN_LIST_GAD];
  136.  gdata[GAD_TOP].name   =AppStrings[MSG_WINDOW_TOP_GAD];
  137.  gdata[GAD_UP].name    =AppStrings[MSG_WINDOW_UP_GAD];
  138.  gdata[GAD_DOWN].name  =AppStrings[MSG_WINDOW_DOWN_GAD];
  139.  gdata[GAD_BOTTOM].name=AppStrings[MSG_WINDOW_BOTTOM_GAD];
  140.  gdata[GAD_SORT].name  =AppStrings[MSG_MAINWIN_SORT_GAD];
  141.  gdata[GAD_NEW].name   =AppStrings[MSG_MAINWIN_NEW_GAD];
  142.  gdata[GAD_EDIT].name  =AppStrings[MSG_MAINWIN_EDIT_GAD];
  143.  gdata[GAD_COPY].name  =AppStrings[MSG_MAINWIN_COPY_GAD];
  144.  gdata[GAD_REMOVE].name=AppStrings[MSG_WINDOW_REMOVE_GAD];
  145.  gdata[GAD_SAVE].name  =AppStrings[MSG_MAINWIN_SAVE_GAD];
  146.  gdata[GAD_USE].name   =AppStrings[MSG_MAINWIN_USE_GAD];
  147.  gdata[GAD_TEST].name  =AppStrings[MSG_MAINWIN_TEST_GAD];
  148.  gdata[GAD_CANCEL].name=AppStrings[MSG_WINDOW_CANCEL_GAD];
  149.  cyclelabels[TMOBJTYPE_EXEC]  =AppStrings[MSG_MAINWIN_TYPE_EXEC_CYCLE_LABEL];
  150.  cyclelabels[TMOBJTYPE_IMAGE] =AppStrings[MSG_MAINWIN_TYPE_IMAGE_CYCLE_LABEL];
  151.  cyclelabels[TMOBJTYPE_SOUND] =AppStrings[MSG_MAINWIN_TYPE_SOUND_CYCLE_LABEL];
  152.  cyclelabels[TMOBJTYPE_MENU]  =AppStrings[MSG_MAINWIN_TYPE_MENU_CYCLE_LABEL];
  153.  cyclelabels[TMOBJTYPE_ICON]  =AppStrings[MSG_MAINWIN_TYPE_ICON_CYCLE_LABEL];
  154.  cyclelabels[TMOBJTYPE_DOCK]  =AppStrings[MSG_MAINWIN_TYPE_DOCK_CYCLE_LABEL];
  155.  cyclelabels[TMOBJTYPE_ACCESS]=AppStrings[MSG_MAINWIN_TYPE_ACCESS_CYCLE_LABEL];
  156.  cyclelabels[TMOBJTYPES]      =NULL;
  157.  
  158.  mdata[MENU_PROJECT].nm_Label  =AppStrings[MSG_MAINWIN_PROJECT_MENU_LABEL];
  159.  mdata[MENU_OPEN].nm_Label     =AppStrings[MSG_MAINWIN_OPEN_MENU_LABEL];
  160.  mdata[MENU_OPEN].nm_CommKey   =AppStrings[MSG_MAINWIN_OPEN_MENU_SHORTCUT];
  161.  mdata[MENU_APPEND].nm_Label   =AppStrings[MSG_MAINWIN_APPEND_MENU_LABEL];
  162.  mdata[MENU_SAVEAS].nm_Label   =AppStrings[MSG_MAINWIN_SAVEAS_MENU_LABEL];
  163.  mdata[MENU_SAVEAS].nm_CommKey =AppStrings[MSG_MAINWIN_SAVEAS_MENU_SHORTCUT];
  164.  mdata[MENU_ABOUT].nm_Label    =AppStrings[MSG_MAINWIN_ABOUT_MENU_LABEL];
  165.  mdata[MENU_QUIT].nm_Label     =AppStrings[MSG_MAINWIN_QUIT_MENU_LABEL];
  166.  mdata[MENU_QUIT].nm_CommKey   =AppStrings[MSG_MAINWIN_QUIT_MENU_SHORTCUT];
  167.  mdata[MENU_EDIT].nm_Label     =AppStrings[MSG_MAINWIN_EDIT_MENU_LABEL];
  168.  mdata[MENU_LSAVED].nm_Label   =AppStrings[MSG_MAINWIN_LASTSAVED_MENU_LABEL];
  169.  mdata[MENU_LSAVED].nm_CommKey =AppStrings[MSG_MAINWIN_LASTSAVED_MENU_SHORTCUT];
  170.  mdata[MENU_RESTORE].nm_Label  =AppStrings[MSG_MAINWIN_RESTORE_MENU_LABEL];
  171.  mdata[MENU_RESTORE].nm_CommKey=AppStrings[MSG_MAINWIN_RESTORE_MENU_SHORTCUT];
  172.  mdata[MENU_SETTING].nm_Label  =AppStrings[MSG_MAINWIN_SETTINGS_MENU_LABEL];
  173.  mdata[MENU_CRICONS].nm_Label  =AppStrings[MSG_MAINWIN_CREATEICONS_MENU_LABEL];
  174.  mdata[MENU_CRICONS].nm_CommKey=
  175.                              AppStrings[MSG_MAINWIN_CREATEICONS_MENU_SHORTCUT];
  176.  mdata[MENU_CRICONS].nm_Flags=CHECKIT|MENUTOGGLE| (CreateIcons ? CHECKED : 0);
  177.  
  178.  /* Calculate maximum width for cycle gadget */
  179.  {
  180.   char **s;
  181.   maxw1=0;
  182.   for (s=cyclelabels; *s; s++)
  183.    if ((tmp=TextLength(&TmpRastPort,*s,strlen(*s))) > maxw1)
  184.     maxw1=tmp;
  185.   maxw1+=4*INTERWIDTH;
  186.  }
  187.  
  188.  /* Calculate size for type gadget text */
  189.  gd=gdata;
  190.  gd->left=TextLength(&TmpRastPort,gd->name,strlen(gd->name))+INTERWIDTH;
  191.  ww=gd->left+maxw1+2*INTERWIDTH;
  192.  
  193.  /* Calculate width for listview gadget */
  194.  gd++;
  195.  gd->width=2*TextLength(&TmpRastPort,gd->name,strlen(gd->name));
  196.  if ((tmp=ListViewColumns*ScreenFont->tf_XSize) > gd->width) gd->width=tmp;
  197.  
  198.  /* Calculate maximum width for move gadgets */
  199.  maxw2=0;
  200.  for (gd++, i=GAD_TOP; i<=GAD_SORT; i++, gd++)
  201.   if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > maxw2)
  202.    maxw2=tmp;
  203.  maxw2+=2*INTERWIDTH;
  204.  if ((tmp=gdata[GAD_LIST].width+maxw2+2*INTERWIDTH) > ww) ww=tmp;
  205.  
  206.  /* Calculate maximum width for manipulation gadgets */
  207.  maxw3=0;
  208.  for (; i<=GAD_CANCEL; i++, gd++)
  209.   if ((tmp=TextLength(&TmpRastPort,gd->name,strlen(gd->name))) > maxw3)
  210.    maxw3=tmp;
  211.  maxw3+=2*INTERWIDTH;
  212.  if ((tmp=4*maxw3+4*INTERWIDTH) > ww) ww=tmp;
  213.  
  214.  /* Calculate window sizes */
  215.  wh=(ListViewRows+3)*fheight+7*INTERHEIGHT;
  216.  
  217.  /* Type gadget */
  218.  gd=&gdata[GAD_TYPE];
  219.  maxw1=ww-gd->left-INTERWIDTH;
  220.  gd->type=CYCLE_KIND;
  221.  gd->flags=PLACETEXT_LEFT;
  222.  gd->tags=cycletags;
  223.  gd->left+=left;
  224.  gd->top=WindowTop+INTERHEIGHT;
  225.  gd->width=maxw1;
  226.  gd->height=fheight;
  227.  
  228.  /* Object list gadget */
  229.  gd++;
  230.  gd->type=LISTVIEW_KIND;
  231.  gd->flags=PLACETEXT_ABOVE;
  232.  gd->tags=lvtags;
  233.  gd->left=left;
  234.  gd->top=WindowTop+2*fheight+3*INTERHEIGHT;
  235.  gd->width=ww-2*INTERWIDTH-maxw2;
  236.  gd->height=(ListViewRows-1)*fheight;
  237.  
  238.  /* Move gadgets */
  239.  maxw1=ww-maxw2-INTERWIDTH+left;
  240.  tmp=gd->top;
  241.  gd++;
  242.  for (i=GAD_TOP; i<=GAD_SORT; i++, gd++, tmp+=fheight+INTERHEIGHT) {
  243.   gd->type=BUTTON_KIND;
  244.   gd->flags=PLACETEXT_IN;
  245.   gd->tags=DisabledTags;
  246.   gd->left=maxw1;
  247.   gd->top=tmp;
  248.   gd->width=maxw2;
  249.   gd->height=fheight;
  250.  }
  251.  gdata[GAD_SORT].tags=NULL;
  252.  
  253.  /* Manipulation gadgets */
  254.  maxw1=left;
  255.  maxw2=(ww-INTERWIDTH-maxw3)/3;
  256.  tmp=WindowTop+(ListViewRows+1)*fheight+4*INTERHEIGHT;
  257.  for (i=GAD_NEW; i<=GAD_REMOVE; i++, gd++, maxw1+=maxw2) {
  258.   gd->type=BUTTON_KIND;
  259.   gd->flags=PLACETEXT_IN;
  260.   gd->tags=DisabledTags;
  261.   gd->left=maxw1;
  262.   gd->top=tmp;
  263.   gd->width=maxw3;
  264.   gd->height=fheight;
  265.  }
  266.  gdata[GAD_NEW].tags=NULL;
  267.  gdata[GAD_REMOVE].left=ww-maxw3-INTERWIDTH+left;
  268.  
  269.  /* Configuration gadgets */
  270.  maxw1=left;
  271.  tmp+=fheight+2*INTERHEIGHT;
  272.  for (; i<=GAD_CANCEL; i++, gd++, maxw1+=maxw2) {
  273.   gd->type=BUTTON_KIND;
  274.   gd->flags=PLACETEXT_IN;
  275.   gd->left=maxw1;
  276.   gd->top=tmp;
  277.   gd->width=maxw3;
  278.   gd->height=fheight;
  279.  }
  280.  gdata[GAD_CANCEL].left=ww-maxw3-INTERWIDTH+left;
  281.  
  282.  /* Init vanilla key array */
  283.  KeyArray[KEY_TYPE]  =FindVanillaKey(gdata[GAD_TYPE].name);
  284.  KeyArray[KEY_SORT]  =FindVanillaKey(gdata[GAD_SORT].name);
  285.  KeyArray[KEY_NEW]   =FindVanillaKey(gdata[GAD_NEW].name);
  286.  KeyArray[KEY_EDIT]  =FindVanillaKey(gdata[GAD_EDIT].name);
  287.  KeyArray[KEY_COPY]  =FindVanillaKey(gdata[GAD_COPY].name);
  288.  KeyArray[KEY_SAVE]  =FindVanillaKey(gdata[GAD_SAVE].name);
  289.  KeyArray[KEY_USE]   =FindVanillaKey(gdata[GAD_USE].name);
  290.  KeyArray[KEY_TEST]  =FindVanillaKey(gdata[GAD_TEST].name);
  291.  KeyArray[KEY_CANCEL]=FindVanillaKey(gdata[GAD_CANCEL].name);
  292.  
  293.  /* Init dummy requester structure */
  294.  InitRequester(&DummyReq);
  295. }
  296.  
  297. /* Open main window */
  298. ULONG OpenMainWindow(UWORD wx, UWORD wy)
  299. {
  300.  /* Create gadgets */
  301.  if (gl=CreateGadgetList(gdata,GADGETS)) {
  302.   /* Create menus */
  303.   if (mn=CreateMenus(mdata,GTMN_FullMenu, TRUE,
  304.                            TAG_DONE)) {
  305.    /* Layout menus */
  306.    if (LayoutMenus(mn,ScreenVI,GTMN_NewLookMenus, TRUE,
  307.                                TAG_DONE))
  308.     /* Open window */
  309.     if (w=OpenWindowTags(NULL,WA_Left,         wx,
  310.                               WA_Top,          wy,
  311.                               WA_InnerWidth,   ww,
  312.                               WA_InnerHeight,  wh,
  313.                               WA_AutoAdjust,   TRUE,
  314.                               WA_Title,        AppStrings[MSG_MAINWIN_TITLE],
  315.                               WA_PubScreen,    PublicScreen,
  316.                               WA_Flags,        WFLG_CLOSEGADGET|WFLG_DRAGBAR|
  317.                                                WFLG_DEPTHGADGET|WFLG_ACTIVATE,
  318.                               WA_IDCMP,        WINDOW_IDCMP,
  319.                               WA_NewLookMenus, TRUE,
  320.                               TAG_DONE)) {
  321.      /* Set menu strip */
  322.      if (SetMenuStrip(w,mn)) {
  323.       /* Release public screen */
  324.       UnlockPubScreen(NULL,PublicScreen);
  325.  
  326.       /* Add as AppWindow */
  327.       aw=NULL;
  328.       if (WorkbenchBase && WBScreen)
  329.        /* This call fails if the Workbench is NOT running! */
  330.        aw=AddAppWindowA(0,0,w,AppMsgPort,NULL);
  331.  
  332.       /* Add gadgets to window */
  333.       AddGList(w,gl,(UWORD) -1,(UWORD) -1,NULL);
  334.       RefreshGList(gl,w,NULL,(UWORD) -1);
  335.       GT_RefreshWindow(w,NULL);
  336.  
  337.       /* Set local variables */
  338.       IDCMPPort=w->UserPort;
  339.       w->UserData=(BYTE *) HandleMainWindowIDCMP;
  340.       CurrentWindow=w;
  341.       if (aw) HandleAppMsg=HandleMainWindowAppMsg;
  342.  
  343.       /* All OK. (Return IDCMP signal mask) */
  344.       return(1L << IDCMPPort->mp_SigBit);
  345.      }
  346.      CloseWindow(w);
  347.    }
  348.    FreeMenus(mn);
  349.   }
  350.   FreeGadgets(gl);
  351.  }
  352.  /* Call failed */
  353.  return(0);
  354. }
  355.  
  356. /* Close main window */
  357. void CloseMainWindow(void)
  358. {
  359.  /* Free resources */
  360.  RemoveGList(w,gl,(UWORD) -1);
  361.  if (aw) {
  362.   HandleAppMsg=NULL;
  363.   RemoveAppWindow(aw);
  364.  }
  365.  ClearMenuStrip(w);
  366.  CloseWindow(w);
  367.  FreeMenus(mn);
  368.  FreeGadgets(gl);
  369. }
  370.  
  371. /* Detach list */
  372. static void DetachObjectList(void)
  373. {
  374.  GT_SetGadgetAttrs(gdata[GAD_LIST].gadget,w,NULL,GTLV_Labels,-1,
  375.                                                  TAG_DONE);
  376. }
  377.  
  378. /* Attach list */
  379. static void AttachObjectList(void)
  380. {
  381.  GT_SetGadgetAttrs(gdata[GAD_LIST].gadget,w,NULL,GTLV_Labels,   CurrentList,
  382.                                                  GTLV_Top,      CurrentTop,
  383.                                                  GTLV_Selected, CurrentOrd,
  384.                                                  TAG_DONE);
  385. }
  386.  
  387. /* Disable object gadgets */
  388. static void DisableObjectGadgets(BOOL disable)
  389. {
  390.  DisableGadget(gdata[GAD_TOP].gadget,w,disable);
  391.  DisableGadget(gdata[GAD_UP].gadget,w,disable);
  392.  DisableGadget(gdata[GAD_DOWN].gadget,w,disable);
  393.  DisableGadget(gdata[GAD_BOTTOM].gadget,w,disable);
  394.  DisableGadget(gdata[GAD_EDIT].gadget,w,disable);
  395.  DisableGadget(gdata[GAD_COPY].gadget,w,disable);
  396.  DisableGadget(gdata[GAD_REMOVE].gadget,w,disable);
  397. }
  398.  
  399. /* Handle application messages */
  400. void HandleMainWindowAppMsg(struct AppMessage *msg)
  401. {
  402.  struct WBArg *wa;
  403.  
  404.  DEBUG_PRINTF("AppMsg 0x%08lx\n",msg);
  405.  
  406.  /* Get first argument */
  407.  if (wa=msg->am_ArgList) {
  408.   BPTR olddir;
  409.   struct DiskObject *dobj;
  410.  
  411.   DEBUG_PRINTF("Argument 0x%08lx\n",wa);
  412.  
  413.   /* Go to new current dir */
  414.   olddir=CurrentDir(wa->wa_Lock);
  415.  
  416.   /* Get icon */
  417.   if (dobj=GetDiskObjectNew(wa->wa_Name)) {
  418.  
  419.    /* Open selection window */
  420.    switch (dobj->do_Type) {
  421.     case WBTOOL:
  422.     case WBPROJECT: if (!UpdateWindow)
  423.                      if (OpenSelectWindow(wa,w)) {
  424.                       /* Disable window */
  425.                       DisableWindow(w,&DummyReq);
  426.  
  427.                       /* Detach object list */
  428.                       DetachObjectList();
  429.  
  430.                       /* Deactivate object gadgets */
  431.                       DisableObjectGadgets(TRUE);
  432.  
  433.                       /* Set update function */
  434.                       UpdateWindow=UpdateAppMainWindow;
  435.                      } else
  436.                       DisplayBeep(NULL);
  437.                     break;
  438.     default:        DisplayBeep(NULL);
  439.                     break;
  440.    }
  441.  
  442.    /* Free icon */
  443.    FreeDiskObject(dobj);
  444.   } else
  445.    DisplayBeep(NULL);
  446.  
  447.   CurrentDir(olddir);
  448.  }
  449. }
  450.  
  451. /* Display write error requester */
  452. static void ConfigWriteError(char *s)
  453. {
  454.  es.es_TextFormat=AppStrings[MSG_MAINWIN_WRITE_ERROR];
  455.  es.es_GadgetFormat=AppStrings[MSG_FILEREQ_CANCEL_GAD];
  456.  
  457.  EasyRequest(w,&es,NULL,s);
  458. }
  459.  
  460. /* Open or append config file */
  461. static void LoadConfigFile(BOOL delobjs)
  462. {
  463.  char *file;
  464.  
  465.  FileReqParms.frp_Window=w;
  466.  FileReqParms.frp_Title=AppStrings[MSG_FILEREQ_TITLE_FILE];
  467.  FileReqParms.frp_OKText=AppStrings[MSG_FILEREQ_OK_GAD];
  468.  FileReqParms.frp_Flags1=FRF_DOPATTERNS;
  469.  FileReqParms.frp_Flags2=FRF_REJECTICONS;
  470.  FileReqParms.frp_OldFile=PrefsFileName;
  471.  
  472.  /* Get file name */
  473.  if (file=OpenFileRequester(&DummyReq)) {
  474.   /* Detach object list */
  475.   DetachObjectList();
  476.  
  477.   /* Deactivate object gadgets */
  478.   DisableObjectGadgets(TRUE);
  479.  
  480.   /* Free all preferences objects */
  481.   if (delobjs) FreeAllObjects();
  482.  
  483.   /* Set wait pointer */
  484.   DisableWindow(w,&DummyReq);
  485.  
  486.   /* Read new config file */
  487.   if (!ReadConfigFile(file)) DisplayBeep(NULL);
  488.  
  489.   /* Remove wait pointer */
  490.   EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  491.  
  492.   /* Set new pointers */
  493.   CurrentList=&ObjectLists[CurrentListNumber];
  494.   CurrentNode=NULL;
  495.   CurrentTop=0;
  496.   CurrentOrd=-1;
  497.  
  498.   /* Free file name */
  499.   free(file);
  500.  
  501.   /* Attach object list */
  502.   AttachObjectList();
  503.  }
  504. }
  505.  
  506. /* Type gadget function */
  507. static void TypeGadgetFunc(ULONG num)
  508. {
  509.  /* Set new Exec list in ListView gadget, detach list */
  510.  DetachObjectList();
  511.  
  512.  /* Set new pointers */
  513.  CurrentList=&ObjectLists[num];
  514.  CurrentListNumber=num;
  515.  CurrentNode=NULL;
  516.  CurrentTop=0;
  517.  CurrentOrd=-1;
  518.  
  519.  /* Set new function pointers */
  520.  OpenEditWindow=OpenEditWindowFunctions[num];
  521.  CopyNode=CopyNodeFunctions[num];
  522.  FreeNode=FreeNodeFunctions[num];
  523.  
  524.  /* Disable object gadgets, attach list */
  525.  DisableObjectGadgets(TRUE);
  526.  AttachObjectList();
  527. }
  528.  
  529. /* Sort gadget function */
  530. static void SortGadgetFunc(void)
  531. {
  532.  BOOL notfinished=TRUE;
  533.  
  534.  /* Detach object list */
  535.  DetachObjectList();
  536.  
  537.  /* Sort list (quick & dirty bubble sort) */
  538.  while (notfinished) {
  539.   struct Node *first;
  540.  
  541.   /* Reset not finished flag */
  542.   notfinished=FALSE;
  543.  
  544.   /* Get first node */
  545.   if (first=GetHead(CurrentList)) {
  546.    struct Node *second;
  547.  
  548.    /* One bubble sort round */
  549.    while (second=GetSucc(first))
  550.     /* Compare */
  551.     if (stricmp(first->ln_Name,second->ln_Name)>0) {
  552.      /* Swap */
  553.      Remove(first);
  554.      Insert(CurrentList,first,second);
  555.      notfinished=TRUE;
  556.     } else
  557.      /* Next */
  558.      first=second;
  559.   }
  560.  }
  561.  
  562.  /* Reset pointers */
  563.  CurrentNode=NULL;
  564.  CurrentOrd=-1;
  565.  CurrentTop=0;
  566.  
  567.  /* Deactivate object gadgets */
  568.  DisableObjectGadgets(TRUE);
  569.  
  570.  /* Attach object list */
  571.  AttachObjectList();
  572. }
  573.  
  574. /* New & Edit gadget function */
  575. static void EditGadgetFunc(struct Node *editnode)
  576. {
  577.  if (!UpdateWindow) {
  578.   /* Save old node */
  579.   OldNode=editnode;
  580.  
  581.   /* Open edit window */
  582.   if ((*OpenEditWindow)(editnode,w)) {
  583.    /* Disable window */
  584.    DisableWindow(w,&DummyReq);
  585.  
  586.    /* Set update function */
  587.    UpdateWindow=UpdateMainWindow;
  588.   } else
  589.    DisplayBeep(NULL);
  590.  }
  591. }
  592.  
  593. /* Copy gadget function */
  594. static void CopyGadgetFunc(void)
  595. {
  596.  if (CurrentNode) {
  597.   struct Node *newnode;
  598.  
  599.   /* Detach object list */
  600.   DetachObjectList();
  601.  
  602.   /* Copy node */
  603.   if (newnode=(*CopyNode)(CurrentNode)) {
  604.    /* Insert new node */
  605.    Insert(CurrentList,newnode,CurrentNode);
  606.  
  607.    /* Reset pointers */
  608.    CurrentNode=newnode;
  609.    CurrentOrd++;
  610.    CurrentTop=(CurrentOrd>ListViewRows-4) ? CurrentOrd-ListViewRows+4 : 0;
  611.   }
  612.  
  613.   /* Attach object list */
  614.   AttachObjectList();
  615.  }
  616. }
  617.  
  618. /* Save gadget function */
  619. static void *SaveGadgetFunc(void)
  620. {
  621.  void *rc=NULL;
  622.  
  623.  /* Set wait pointer */
  624.  DisableWindow(w,&DummyReq);
  625.  
  626.  /* Save config file */
  627.  if (WriteConfigFile(SavePrefsFileName))
  628.   if (CopyFile(SavePrefsFileName,PrefsFileName))
  629.    rc=(void *) 1;
  630.   else
  631.    ConfigWriteError(PrefsFileName);
  632.  else
  633.   ConfigWriteError(SavePrefsFileName);
  634.  
  635.  /* Remove wait pointer */
  636.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  637.  return(rc);
  638. }
  639.  
  640. /* Use gadget function */
  641. static void *UseGadgetFunc(void)
  642. {
  643.  void *rc=NULL;
  644.  
  645.  /* Set wait pointer */
  646.  DisableWindow(w,&DummyReq);
  647.  
  648.  /* Save config file */
  649.  if (WriteConfigFile(PrefsFileName))
  650.   rc=(void *) 1;
  651.  else
  652.   ConfigWriteError(PrefsFileName);
  653.  
  654.  /* Remove wait pointer */
  655.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  656.  return(rc);
  657. }
  658.  
  659. /* Test gadget function */
  660. static void TestGadgetFunc(void)
  661. {
  662.  /* Set wait pointer */
  663.  DisableWindow(w,&DummyReq);
  664.  
  665.  /* Save config file */
  666.  if (!WriteConfigFile(PrefsFileName))
  667.   ConfigWriteError(PrefsFileName);
  668.  
  669.  /* Remove wait pointer */
  670.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  671. }
  672.  
  673. /* Handle main window IDCMP events */
  674. void *HandleMainWindowIDCMP(struct IntuiMessage *msg)
  675. {
  676.  void *closewindow=NULL;
  677.  
  678.  /* Which IDCMP class? */
  679.  switch (msg->Class) {
  680.   case IDCMP_CLOSEWINDOW:   if (!UpdateWindow) closewindow=(void *) 1;
  681.                             break;
  682.   case IDCMP_REFRESHWINDOW: GT_BeginRefresh(w);
  683.                             GT_EndRefresh(w,TRUE);
  684.                             break;
  685.   case IDCMP_GADGETUP:
  686.    switch (((struct Gadget *) msg->IAddress)->GadgetID) {
  687.     case GAD_TYPE:   TypeGadgetFunc(msg->Code);
  688.                      break;
  689.     case GAD_LIST:   {
  690.                       ULONG i;
  691.                       LONG OldOrd;
  692.  
  693.                       /* Find node */
  694.                       OldOrd=CurrentOrd;
  695.                       CurrentOrd=msg->Code;
  696.                       CurrentTop=(CurrentOrd>ListViewRows-4) ?
  697.                                   CurrentOrd-ListViewRows+4 : 0;
  698.                       CurrentNode=GetHead(CurrentList);
  699.                       for (i=0; i<CurrentOrd; i++)
  700.                        CurrentNode=GetSucc(CurrentNode);
  701.  
  702.                       /* Double click? */
  703.                       if (DoubleClick(CurrentSeconds,CurrentMicros,
  704.                                       msg->Seconds,msg->Micros) &&
  705.                           (CurrentOrd == OldOrd) && !UpdateWindow &&
  706.                           CurrentNode) {
  707.                        /* Save pointer to node */
  708.                        OldNode=CurrentNode;
  709.  
  710.                        /* Open edit window */
  711.                        if ((*OpenEditWindow)(CurrentNode,w)) {
  712.                         /* Disable window */
  713.                         DisableWindow(w,&DummyReq);
  714.  
  715.                         /* Set update function */
  716.                         UpdateWindow=UpdateMainWindow;
  717.                        } else
  718.                         DisplayBeep(NULL);
  719.                       }
  720.  
  721.                       /* Activate object gadgets */
  722.                       DisableObjectGadgets(FALSE);
  723.  
  724.                       /* Save current time */
  725.                       CurrentSeconds=msg->Seconds;
  726.                       CurrentMicros=msg->Micros;
  727.                      }
  728.                      break;
  729.     case GAD_TOP:    if (CurrentNode) {
  730.                       /* Detach object list */
  731.                       DetachObjectList();
  732.  
  733.                       /* Move node to top of list */
  734.                       Remove(CurrentNode);
  735.                       AddHead(CurrentList,CurrentNode);
  736.                       CurrentTop=0;
  737.                       CurrentOrd=0;
  738.  
  739.                       /* Attach object list */
  740.                       AttachObjectList();
  741.                      }
  742.                      break;
  743.     case GAD_UP:     {
  744.                       struct Node *pred;
  745.  
  746.                       /* Node valid and has a predecessor? */
  747.                       if (CurrentNode && (pred=GetPred(CurrentNode))) {
  748.                        /* Detach object list */
  749.                        DetachObjectList();
  750.  
  751.                        /* Move node one position up */
  752.                        pred=GetPred(pred);
  753.                        Remove(CurrentNode);
  754.                        Insert(CurrentList,CurrentNode,pred);
  755.                        --CurrentOrd;
  756.                        CurrentTop=(CurrentOrd>ListViewRows-4) ?
  757.                                    CurrentOrd-ListViewRows+4 : 0;
  758.  
  759.                        /* Attach object list */
  760.                        AttachObjectList();
  761.                       }
  762.                      }
  763.                      break;
  764.     case GAD_DOWN:   {
  765.                       struct Node *succ;
  766.  
  767.                       /* Node valid and has a successor? */
  768.                       if (CurrentNode && (succ=GetSucc(CurrentNode))) {
  769.                        /* Detach object list */
  770.                        DetachObjectList();
  771.  
  772.                        /* Move node one position down */
  773.                        Remove(CurrentNode);
  774.                        Insert(CurrentList,CurrentNode,succ);
  775.                        ++CurrentOrd;
  776.                        CurrentTop=(CurrentOrd>ListViewRows-4) ?
  777.                                    CurrentOrd-ListViewRows+4 : 0;
  778.  
  779.                        /* Attach object list */
  780.                        AttachObjectList();
  781.                       }
  782.                      }
  783.                      break;
  784.     case GAD_BOTTOM: if (CurrentNode) {
  785.                       ULONG i;
  786.                       struct Node *tmpnode;
  787.  
  788.                       /* Detach object list */
  789.                       DetachObjectList();
  790.  
  791.                       /* Move tool to bottom of list */
  792.                       Remove(CurrentNode);
  793.                       AddTail(CurrentList,CurrentNode);
  794.  
  795.                       /* Search ordinal number */
  796.                       tmpnode=GetHead(CurrentList);
  797.                       for (i=0; tmpnode; i++) tmpnode=GetSucc(tmpnode);
  798.                       CurrentOrd=--i;
  799.                       CurrentTop=(i>ListViewRows-4) ? i-ListViewRows+4 : 0;
  800.  
  801.                       /* Attach object list */
  802.                       AttachObjectList();
  803.                      }
  804.                      break;
  805.     case GAD_SORT:   SortGadgetFunc();
  806.                      break;
  807.     case GAD_NEW:    EditGadgetFunc(NULL);
  808.                      break;
  809.     case GAD_EDIT:   EditGadgetFunc(CurrentNode);
  810.                      break;
  811.     case GAD_COPY:   CopyGadgetFunc();
  812.                      break;
  813.     case GAD_REMOVE: /* Remove current node */
  814.                      if (CurrentNode) {
  815.                       /* Detach object list */
  816.                       DetachObjectList();
  817.  
  818.                       /* Deactivate object gadgets */
  819.                       DisableObjectGadgets(TRUE);
  820.  
  821.                       /* Remove node from list */
  822.                       Remove(CurrentNode);
  823.  
  824.                       /* Free node */
  825.                       (*FreeNode)(CurrentNode);
  826.  
  827.                       /* Reset pointers */
  828.                       CurrentNode=NULL;
  829.                       CurrentTop=(CurrentOrd>ListViewRows-4) ?
  830.                                   CurrentOrd-ListViewRows+4 : 0;
  831.                       CurrentOrd=-1;
  832.  
  833.                       /* Attach object list */
  834.                       AttachObjectList();
  835.                      }
  836.                      break;
  837.     case GAD_SAVE:   closewindow=SaveGadgetFunc();
  838.                      break;
  839.     case GAD_USE:    closewindow=UseGadgetFunc();
  840.                      break;
  841.     case GAD_TEST:   TestGadgetFunc();
  842.                      break;
  843.     case GAD_CANCEL: if (!UpdateWindow) closewindow=(void *) 1;
  844.                      break;
  845.    }
  846.    break;
  847.   case IDCMP_VANILLAKEY:
  848.    switch (MatchVanillaKey(msg->Code,KeyArray)) {
  849.     case KEY_TYPE:   {
  850.                       /* Get next cycle gadget code */
  851.                       ULONG type;
  852.  
  853.                       /* Forward or backward cycle? */
  854.                       if (islower(msg->Code))
  855.                        type=(CurrentListNumber+1) % TMOBJTYPES;
  856.                       else
  857.                        type=(CurrentListNumber>0) ? CurrentListNumber-1 :
  858.                                                     TMOBJTYPE_ACCESS;
  859.  
  860.                       /* Set cycle gadget */
  861.                       GT_SetGadgetAttrs(gdata[GAD_TYPE].gadget,w,NULL,
  862.                                         GTCY_Active, type,
  863.                                         TAG_DONE);
  864.  
  865.                       /* Update data */
  866.                       TypeGadgetFunc(type);
  867.                      }
  868.                      break;
  869.     case KEY_SORT:   SortGadgetFunc();
  870.                      break;
  871.     case KEY_NEW:    EditGadgetFunc(NULL);
  872.                      break;
  873.     case KEY_EDIT:   if (CurrentNode) EditGadgetFunc(CurrentNode);
  874.                      break;
  875.     case KEY_COPY:   CopyGadgetFunc();
  876.                      break;
  877.     case KEY_SAVE:   closewindow=SaveGadgetFunc();
  878.                      break;
  879.     case KEY_USE:    closewindow=UseGadgetFunc();
  880.                      break;
  881.     case KEY_TEST:   TestGadgetFunc();
  882.                      break;
  883.     case KEY_CANCEL: if (!UpdateWindow) closewindow=(void *) 1;
  884.                      break;
  885.    }
  886.    break;
  887.   case IDCMP_MENUPICK: {
  888.     USHORT menunum=msg->Code;
  889.  
  890.     /* Scan all menu events */
  891.     while (menunum!=MENUNULL) {
  892.      struct MenuItem *menuitem=ItemAddress(mn,menunum);
  893.  
  894.      /* Which menu selected? */
  895.      switch(GTMENUITEM_USERDATA(menuitem)) {
  896.       case MENU_OPEN:    LoadConfigFile(TRUE);
  897.                          break;
  898.       case MENU_APPEND:  LoadConfigFile(FALSE);
  899.                          break;
  900.       case MENU_SAVEAS:  {
  901.                           char *file;
  902.  
  903.                           FileReqParms.frp_Window=w;
  904.                           FileReqParms.frp_Title=
  905.                              AppStrings[MSG_FILEREQ_TITLE_FILE];
  906.                           FileReqParms.frp_OKText=
  907.                              AppStrings[MSG_FILEREQ_SAVE_GAD];
  908.                           FileReqParms.frp_Flags1=FRF_DOSAVEMODE;
  909.                           FileReqParms.frp_Flags2=FRF_REJECTICONS;
  910.                           FileReqParms.frp_OldFile=SavePrefsFileName;
  911.  
  912.                           /* Get file name */
  913.                           if (file=OpenFileRequester(&DummyReq)) {
  914.                            /* Set wait pointer */
  915.                            DisableWindow(w,&DummyReq);
  916.  
  917.                            /* Read new config file */
  918.                            if (WriteConfigFile(file)) {
  919.                             /* Create icon for file? */
  920.                             if (CreateIcons) {
  921.                              struct DiskObject *dobj;
  922.  
  923.                              /* Get project icon */
  924.                              if (dobj=
  925.                                   GetDiskObjectNew(file)) {
  926.                               char *deftool=dobj->do_DefaultTool;
  927.                               char **tooltypes=dobj->do_ToolTypes;
  928.                               UBYTE type=dobj->do_Type;
  929.  
  930.                               /* Set new values */
  931.                               dobj->do_DefaultTool=ProgramName;
  932.                               dobj->do_ToolTypes=deftooltypes;
  933.                               dobj->do_Type=WBPROJECT;
  934.  
  935.                               /* Write icon */
  936.                               PutDiskObject(file,dobj);
  937.  
  938.                               /* Set old values */
  939.                               dobj->do_DefaultTool=deftool;
  940.                               dobj->do_ToolTypes=tooltypes;
  941.                               dobj->do_Type=type;
  942.  
  943.                               /* Free icon */
  944.                               FreeDiskObject(dobj);
  945.                              }
  946.                             }
  947.                            } else
  948.                             /* error occurred */
  949.                             ConfigWriteError(file);
  950.  
  951.                            /* Remove wait pointer */
  952.                            EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  953.  
  954.                            /* Free file name */
  955.                            free(file);
  956.                           }
  957.                          }
  958.                          break;
  959.       case MENU_ABOUT:   es.es_TextFormat="ToolManager " TMVERSION "."
  960.                                           TMREVISION " (" __COMMODORE_DATE__
  961.                                           ")\nFreely distributable\n"
  962.                                           "© " TMCRYEAR "  Stefan Becker";
  963.                          es.es_GadgetFormat=AppStrings[MSG_FILEREQ_CANCEL_GAD];
  964.  
  965.                          /* Disable window */
  966.                          DisableWindow(w,&DummyReq);
  967.  
  968.                          /* Display requester */
  969.                          EasyRequest(w,&es,NULL,NULL);
  970.  
  971.                          /* Enable window */
  972.                          EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  973.                          break;
  974.       case MENU_QUIT:    if (!UpdateWindow) closewindow=(void *) 1;
  975.                          break;
  976.       case MENU_LSAVED:  {
  977.                           /* Detach object list */
  978.                           DetachObjectList();
  979.  
  980.                           /* Deactivate object gadgets */
  981.                           DisableObjectGadgets(TRUE);
  982.  
  983.                           /* Free all preferences objects */
  984.                           FreeAllObjects();
  985.  
  986.                           /* Set wait pointer */
  987.                           DisableWindow(w,&DummyReq);
  988.  
  989.                           /* Read new config file */
  990.                           if (!ReadConfigFile(SavePrefsFileName))
  991.                            DisplayBeep(NULL);
  992.  
  993.                           /* Remove wait pointer */
  994.                           EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  995.  
  996.                           /* Set new pointers */
  997.                           CurrentList=&ObjectLists[CurrentListNumber];
  998.                           CurrentNode=NULL;
  999.                           CurrentTop=0;
  1000.                           CurrentOrd=-1;
  1001.  
  1002.                           /* Attach object list */
  1003.                           AttachObjectList();
  1004.                          }
  1005.                          break;
  1006.       case MENU_RESTORE: {
  1007.                           /* Detach object list */
  1008.                           DetachObjectList();
  1009.  
  1010.                           /* Deactivate object gadgets */
  1011.                           DisableObjectGadgets(TRUE);
  1012.  
  1013.                           /* Free all preferences objects */
  1014.                           FreeAllObjects();
  1015.  
  1016.                           /* Set wait pointer */
  1017.                           DisableWindow(w,&DummyReq);
  1018.  
  1019.                           /* Read new config file */
  1020.                           if (!ReadConfigFile(PrefsFileName)) DisplayBeep(NULL);
  1021.  
  1022.                           /* Remove wait pointer */
  1023.                           EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  1024.  
  1025.                           /* Set new pointers */
  1026.                           CurrentList=&ObjectLists[CurrentListNumber];
  1027.                           CurrentNode=NULL;
  1028.                           CurrentTop=0;
  1029.                           CurrentOrd=-1;
  1030.  
  1031.                           /* Attach object list */
  1032.                           AttachObjectList();
  1033.                          }
  1034.                          break;
  1035.       case MENU_CRICONS: CreateIcons=(menuitem->Flags & CHECKED) != 0;
  1036.                          break;
  1037.      }
  1038.  
  1039.      /* Get next menu event number */
  1040.      menunum=menuitem->NextSelect;
  1041.     }
  1042.    }
  1043.    break;
  1044.  }
  1045.  
  1046.  /* Close Window? */
  1047.  if (closewindow) GT_ReplyIMsg(msg);
  1048.  
  1049.  return(closewindow);
  1050. }
  1051.  
  1052. /* Update main window (after the select window has closed) */
  1053. void UpdateAppMainWindow(void *data)
  1054. {
  1055.  /* Lists changed? */
  1056.  if (data!=(void *) -1) {
  1057.  
  1058.   /* Clear pointers */
  1059.   CurrentNode=NULL;
  1060.   CurrentTop=0;
  1061.   CurrentOrd=-1;
  1062.  }
  1063.  
  1064.  /* Activate Gadgets */
  1065.  DisableObjectGadgets(CurrentNode==NULL);
  1066.  
  1067.  /* Attach object list */
  1068.  AttachObjectList();
  1069.  
  1070.  /* Enable window */
  1071.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  1072.  
  1073.  /* Restore update function pointer */
  1074.  UpdateWindow=NULL;
  1075.  CurrentWindow=w;
  1076. }
  1077.  
  1078.  
  1079. /* Update main window (after an edit window has closed) */
  1080. void UpdateMainWindow(void *data)
  1081. {
  1082.  /* Detach object list */
  1083.  DetachObjectList();
  1084.  
  1085.  DEBUG_PRINTF("OldNode: 0x%08lx ",OldNode);
  1086.  DEBUG_PRINTF("NewNode: 0x%08lx\n",data);
  1087.  
  1088.  /* Node changed? */
  1089.  if (data!=(void *) -1) {
  1090.   struct Node *NewNode=data;
  1091.  
  1092.   /* Make sure that ln_Name is valid */
  1093.   if (!NewNode->ln_Name) NewNode->ln_Name=strdup("");
  1094.  
  1095.   /* Yes. New or Edit? */
  1096.   if (OldNode) {
  1097.    /* Edit. Insert new node */
  1098.    Insert(CurrentList,NewNode,OldNode);
  1099.  
  1100.    /* Remove old node */
  1101.    Remove(OldNode);
  1102.  
  1103.    /* Free old node */
  1104.    (*FreeNode)(OldNode);
  1105.  
  1106.    /* Set pointer */
  1107.    CurrentNode=NewNode;
  1108.   } else {
  1109.    /* New. Insert after selected node? */
  1110.    if (CurrentNode) {
  1111.     /* Yes */
  1112.     Insert(CurrentList,NewNode,CurrentNode);
  1113.     CurrentOrd++;
  1114.     CurrentTop=(CurrentOrd>ListViewRows-4) ? CurrentOrd-ListViewRows+4 : 0;
  1115.    } else {
  1116.     /* No */
  1117.     struct Node *tmpnode;
  1118.     ULONG i;
  1119.  
  1120.     /* Add node to the end of list */
  1121.     AddTail(CurrentList,NewNode);
  1122.  
  1123.     /* Search ordinal number */
  1124.     tmpnode=GetHead(CurrentList);
  1125.     for (i=0; tmpnode; i++) tmpnode=GetSucc(tmpnode);
  1126.     CurrentOrd=--i;
  1127.     CurrentTop=(i>ListViewRows-4) ? i-ListViewRows+4 : 0;
  1128.    }
  1129.    CurrentNode=NewNode;
  1130.   }
  1131.  }
  1132.  
  1133.  /* Activate Gadgets */
  1134.  DisableObjectGadgets(CurrentNode==NULL);
  1135.  
  1136.  /* Attach object list */
  1137.  AttachObjectList();
  1138.  
  1139.  /* Enable window */
  1140.  EnableWindow(w,&DummyReq,WINDOW_IDCMP);
  1141.  
  1142.  /* Restore update function pointer */
  1143.  UpdateWindow=NULL;
  1144.  CurrentWindow=w;
  1145. }
  1146.